package xj.model.uml;

import static xj.model.uml.UMLModelConstants.ATTR_END;
import static xj.model.uml.UMLModelConstants.ATTR_START;
import static xj.model.uml.UMLModelConstants.ROLE_EXECUTION_OCCURANCE;
import static xj.model.uml.UMLModelConstants.ROLE_OBJECT_REF;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import xj.meta.ModelElement;
import xj.meta.ModelReference;
import xj.meta.ModelRepository;
import xj.meta.ReferenceElement;

public class ExecutionOccurance 
  extends NamedElement 
  implements ModelReference, MessageNode {

  public ExecutionOccurance() {
    this(null, null);
  }

  public ExecutionOccurance(String name) {
    this(name, null);
  }

  public ExecutionOccurance(UMLObject c) {
    this(null, c);
  }

  public ExecutionOccurance(String name, UMLObject c) {
    super(name);
    setUMLObject(c);
  }

  public int getStart() {
    return start;
  }

  public void setStart(int start) {
    this.start = start;
    setAttribute(ATTR_START, start);
  }

  public int getEnd() {
    return end;
  }

  public void setEnd(int end) {
    this.end = end;
    setAttribute(ATTR_END, end);
  }

  public void setInterval(int start, int end) {
    setStart(start);
    setEnd(end);
  }

  public UMLObject getUMLObject() {
    return object;
  }

  public void setUMLObject(UMLObject o) {
    object = o;
    if (o != null) {
      if (objRef == null) {
	objRef = new ReferenceElement(o);
      } else {
	objRef.setReference(o);
      }
    } else {
      objRef = null;
    }
    setOwnedElement(ROLE_OBJECT_REF, objRef);
  }

  public ReferenceElement getObjectReference() {
    return objRef;
  }

  public void addReferenceElement(ReferenceElement ref) {
    if (ref != null) {
      objRef = ref;
      setOwnedElement(ROLE_OBJECT_REF, ref);
    }
  }

  public void linkObject() {
    if (object == null && objRef != null) {
      ModelRepository rep = ModelRepository.getInstance();
      String refid = objRef.getRefid();
      ModelElement o = rep.getElement(refid);
      if (o instanceof UMLObject) {
	object = (UMLObject) o;
      }
    }
  }

  public void resolveLink() {
    linkObject();
  }

  public List<ExecutionOccurance> getExecutionOccurances() {
    return executions;
  }

  public void addExecutionOccurance(ExecutionOccurance e) {
    if (e != null) {
      executions.add(e);
      addOwnedElement(e, ROLE_EXECUTION_OCCURANCE);
    }
  }

  public void removeExecutionOccurance(ExecutionOccurance e) {
    if (e != null) {
      executions.remove(e);
      removeOwnedElement(e);
    }
  }

  @Override
  public Object clone() throws CloneNotSupportedException {
    ExecutionOccurance e = (ExecutionOccurance) super.clone();
    e.setUMLObject(object);
    e.setStart(start);
    e.setEnd(end);

    e.executions = new ArrayList<ExecutionOccurance>();
    Iterator<ExecutionOccurance> iter = executions.iterator();
    while (iter.hasNext()) {
      ExecutionOccurance ex = iter.next();
      ex.addExecutionOccurance((ExecutionOccurance) e.clone());
    }
    return e;
  }

  protected UMLObject object;

  protected ReferenceElement objRef;

  protected int start, end;

  protected List<ExecutionOccurance> executions = new ArrayList<ExecutionOccurance>();

}
